package com.lesserpand.rabbitmq.quartz.utils;

import com.lesserpand.rabbitmq.quartz.service.impl.JobAndTriggerServiceImpl;
import org.quartz.Calendar;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author bailuo
 * @version 2.0
 * @Description TODO
 * @Date Created in 2019/1/19 20:42
 */
@Component
public class QuartzUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(JobAndTriggerServiceImpl.class);

    @Autowired
    private Scheduler scheduler;

    /**
     * 新建定时任务
     * <p>
     * <p>
     * SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(2).repeatForever();简单调度构建器，每2秒执行一次，一直执行
     * <p>
     * AnnualCalendar annualCalendar = new AnnualCalendar();
     * GregorianCalendar nationalDay = new GregorianCalendar(2017, 10, 27);
     * annualCalendar.setDayExcluded(nationalDay, true); 排除的日期，如果为false则为包含
     * CronCalendar cronCalendar = new CronCalendar();
     * DailyCalendar dailyCalendar = new DailyCalendar();
     * HolidayCalendar holidayCalendar = new HolidayCalendar();
     * MonthlyCalendar monthlyCalendar = new MonthlyCalendar();
     * WeeklyCalendar weeklyCalendar = new WeeklyCalendar();
     *
     * @param job            定时任务
     * @param jobClassName   任务名称
     * @param jobGroupName   任务组名称
     * @param cronExpression 执行周期 cron格式
     * @return
     */
    public String createJob(Job job, String jobClassName, String jobGroupName, Map<String, Object> map, String cronExpression) {
        try {

            // 构建job信息
            JobBuilder jobBuilder = JobBuilder
                    .newJob(job.getClass())
                    .withIdentity(jobClassName, jobGroupName);
            if (null != map && !map.isEmpty()) {
                map.forEach((key, value) -> {
                    if (value instanceof String) {
                        jobBuilder.usingJobData(key, (String) value);
                    } else if (value instanceof Integer) {
                        jobBuilder.usingJobData(key, (Integer) value);
                    } else if (value instanceof Long) {
                        jobBuilder.usingJobData(key, (Long) value);
                    } else if (value instanceof Float) {
                        jobBuilder.usingJobData(key, (Float) value);
                    } else if (value instanceof Double) {
                        jobBuilder.usingJobData(key, (Double) value);
                    } else if (value instanceof Boolean) {
                        jobBuilder.usingJobData(key, (Boolean) value);
                    } else {
                        throw new ClassCastException("数据转换异常！");
                    }
                });
            }
            JobDetail jobDetail = jobBuilder.build();

            // 表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobClassName, jobGroupName)
                    .withSchedule(cronScheduleBuilder)
                    .build();
            // 启动调度器
            scheduler.start();
            //
            scheduler.scheduleJob(jobDetail, trigger);
            LOGGER.info("创建定时任务成功");
            return "创建定时任务成功";
        } catch (SchedulerException e) {
            LOGGER.error("创建定时任务失败" + e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 更新定时任务
     *
     * @param jobClassName   任务名称
     * @param jobGroupName   任务组名称
     * @param cronExpression 执行周期 cron格式
     * @return
     * @throws Exception
     */
    public String updateJob(String jobClassName, String jobGroupName, String cronExpression) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger
                    .getTriggerBuilder()
                    .withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder)
                    .build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
            return "更新成功";
        } catch (SchedulerException e) {
            LOGGER.error("更新定时任务失败" + e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除定时任务
     *
     * @param jobClassName 任务名称
     * @param jobGroupName 任务组名称
     * @throws Exception
     */
    public void deleteJob(String jobClassName, String jobGroupName) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
            scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 暂停任务
     *
     * @param jobClassName 任务名称
     * @param jobGroupName 任务组名称
     */
    public void pauseJob(String jobClassName, String jobGroupName) {
        try {
            scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 继续任务
     *
     * @param jobClassName 任务名称
     * @param jobGroupName 任务组名称
     */
    public void resumejob(String jobClassName, String jobGroupName) {
        try {
            scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

}
